#ifdef _WIN32
#include<libserv/libserv.h>
#include<windows.h>
#include <CString>
#include <String.h>
#include <ctime>
#include <tchar.h>
#include<libserv/libserv_message.h>
#define MAX_BUFFER_SIZE 1024
namespace libserv {
    template <typename T> std::queue<T> BaseMessage<T>::message_queue;
    typedef struct _parameter {
        HANDLE fd;
        char head = 0x55;
        int read_buffer_size = MAX_BUFFER_SIZE;
        int args;
        int(*bind_function)(void *, std::vector<char>);
        HANDLE *StopEvent;//服务结束事件
        HANDLE *SendEvent;//串口发送事件
        HANDLE *ReadEvent;//串口发送事件

    } parameter;
    parameter param;
    libserv::Message  *message;


    int default_print_function(void *arg, std::vector<char> message) {
        int args = *((int *)arg);
        std::cout << "Test Serial:" << *((int *)arg) << " Say:";
        std::vector<char>::iterator  it;
        for (it = message.begin(); it < message.end(); it++) {
            std::cout <<std::hex<< *it;
        }
        std::cout<< " Time: " << clock() << std::endl;
        return 0;
    }

    bool default_check_function(std::vector<char> package) {
        return true;
    }
    bool is_empty_package(char* buffer,int buffer_szie) {
        for (int i = 0; i < buffer_szie; i++) {
            if (buffer[i] != '\0')
                return false;
        }
        return true;
    }

    DWORD WINAPI recive_serial_data(LPVOID args) {

        parameter arg_parameter = *((parameter *)args);

        int max_queue_size = arg_parameter.args;
        //数据包包头值
        char head = arg_parameter.head;
        //读取数据的大小
        int read_buffer_size = arg_parameter.read_buffer_size;

        //服务结束事件
        HANDLE StopEvent = *(arg_parameter.StopEvent);
        //串口发送事件
        HANDLE SendEvent = *(arg_parameter.SendEvent);
        //串口发送事件
        HANDLE ReadEvent = *(arg_parameter.ReadEvent);

        HANDLE g_hCom = arg_parameter.fd;
        SetCommMask(g_hCom, EV_RXCHAR);



        while (WaitForSingleObject(StopEvent, IGNORE) != WAIT_OBJECT_0) {
            WaitForSingleObject(ReadEvent, INFINITE);
            ResetEvent(ReadEvent);
            SetEvent(SendEvent);

            OVERLAPPED osWait;
            memset(&osWait, 0, sizeof(OVERLAPPED));
            osWait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
            DWORD dwEvtMask;

            if (WaitCommEvent(g_hCom, &dwEvtMask, &osWait)) {
                if (dwEvtMask != EV_RXCHAR) {
                    DWORD dwError;
                    COMSTAT cs;
                    if (!ClearCommError(g_hCom, &dwError, &cs)) {
                        CloseHandle(g_hCom);
                        break;
                    }
                    char *serial_buffer = new char[read_buffer_size];
                    memset(serial_buffer, 0, MAX_BUFFER_SIZE);
                    DWORD nLenOut = 0;
                    OVERLAPPED osRead;
                    memset(&osRead, 0, sizeof(OVERLAPPED));
                    osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

                    BOOL bReadStatus = ReadFile(g_hCom, serial_buffer, cs.cbInQue, &nLenOut, &osRead);

                    if (!bReadStatus) {
                        if (GetLastError() == ERROR_IO_PENDING) {
                            std::cout << "Recive->" << serial_buffer << std::endl;
                        }
                    }
                    delete serial_buffer;
                }
            }
            else {
                //ERROR_IO_PENDING 表明正在进行读操作
                if (GetLastError() == ERROR_IO_PENDING) {
                    WaitForSingleObject(osWait.hEvent, INFINITE);
                    if (dwEvtMask & EV_RXCHAR) {
                        DWORD dwError;
                        COMSTAT cs;
                        if (!ClearCommError(g_hCom, &dwError, &cs)) {
                            CloseHandle(g_hCom);
                            return false;
                        }
                        char *serial_buffer = new char[read_buffer_size];
                        memset(serial_buffer, 0, MAX_BUFFER_SIZE);
                        DWORD nLenOut = 0;
                        DWORD dwTrans;
                        OVERLAPPED osRead;
                        memset(&osRead, 0, sizeof(OVERLAPPED));
                        osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                        int data_length = cs.cbInQue;
                        BOOL bReadStatus = ReadFile(g_hCom, serial_buffer, cs.cbInQue, &nLenOut, &osRead);

                        if (bReadStatus) {
                            if (data_length > 0) {
                                message->SerialRecive(serial_buffer, data_length);
                                if (!message->IsEmpty()) {
                                    std::vector<char> data_package=message->pop_message();
                                    arg_parameter.bind_function((void *)&arg_parameter.fd, data_package);
                                }
                            }

                            //
                            //PurgeComm(g_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
                        }
                        delete serial_buffer;
                    }
                }
            }


            SetEvent(ReadEvent);
            ResetEvent(SendEvent);
        }
        std::cout << "[ INFO ] " << "Read Thread Terminate" << std::endl;
        return 0;

    }


    Serial::Serial() {
        this->call_function = default_print_function;
        this->check_function = default_check_function;
        //复位方式为手动恢复到无信号状态，且初始状态为有信号.
        this->ReadEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
        //复位方式为手动恢复到无信号状态，且初始状态为无信号.
        this->SendEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        this->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    }

    Serial::Serial(int serial_device, int frequence) {

        this->call_function = default_print_function;
        this->check_function = default_check_function;
        //复位方式为手动恢复到无信号状态，且初始状态为有信号.
        this->ReadEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
        //复位方式为手动恢复到无信号状态，且初始状态为无信号.
        this->SendEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        this->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

        this->BindPort(serial_device, frequence);
    }

    int Serial::BindPort(int serial_device, int frequence) {
        TCHAR PortName[10] = { '\\','\\','.','\\','C','O','M',0,0,0 };//"\\\\.\\COM";
        TCHAR chrTemple[5] = { 0 };

        _itot(serial_device, chrTemple, 10);
        _tcscat(PortName, chrTemple);

        this->hCom = CreateFile(PortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
        if (this->hCom == INVALID_HANDLE_VALUE) {
            int error = GetLastError();
            std::cout << "Serial Open Error:" << PortName << " Code:" << error << std::endl;
            return error;
        }

        //设置读超时
        COMMTIMEOUTS timeouts;
        GetCommTimeouts(this->hCom, &timeouts);
        timeouts.ReadIntervalTimeout = 0;
        timeouts.ReadTotalTimeoutMultiplier = 0;
        timeouts.ReadTotalTimeoutConstant = 60000;
        timeouts.WriteTotalTimeoutMultiplier = 0;
        timeouts.WriteTotalTimeoutConstant = 0;
        SetCommTimeouts(this->hCom, &timeouts);
        static const int g_nZhenMax = 1024 * 8;
        if (!SetupComm(this->hCom, g_nZhenMax, g_nZhenMax)) {
            CloseHandle(this->hCom);
            return -1;
        }

        //设置串口配置信息
        DCB dcb;
        if (!GetCommState(this->hCom, &dcb)) {
            CloseHandle(this->hCom);
            return -1;
        }
        dcb.DCBlength = sizeof(DCB);
        dcb.BaudRate = frequence;//波特率为9600
        dcb.Parity = 0;//校验方式为无校验
        dcb.ByteSize = 8;//数据位为8位
        dcb.StopBits = ONESTOPBIT;//停止位为1位
        if (!SetCommState(this->hCom, &dcb)) {
            CloseHandle(this->hCom);
            return -1;
        }
        //清空缓冲
        PurgeComm(this->hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);

        //清除错误
        DWORD dwError;
        COMSTAT cs;
        if (!ClearCommError(this->hCom, &dwError, &cs)) {
            CloseHandle(this->hCom);
            return -1;
        }
        return 0;
    }

    void Serial::BindCall(int(*bind_function)(void *, std::vector<char>)) {
        this->call_function = (*bind_function);
    }

    void Serial::BindPackageCheck(bool (*check_function)(std::vector<char>)) {
        this->check_function = check_function;
    }

    void Serial::AnsySend(char *buffer, int buffer_size) {
        //接收服务没有在接收数据才可以发送
        WaitForSingleObject(this->SendEvent, INFINITE);
        ResetEvent(this->ReadEvent);

        std::cout<<"Send->"<< (int)buffer[3] <<std::endl;
        OVERLAPPED osWrite = { 0 };
        DWORD dwWritten;
        BOOL fRes;

        osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (osWrite.hEvent == NULL)
            return;

        if (!WriteFile(this->hCom, buffer, buffer_size, &dwWritten, &osWrite)) {
            if (GetLastError() != ERROR_IO_PENDING) {
                fRes = FALSE;
            }
            else {
                if (!GetOverlappedResult(this->hCom, &osWrite, &dwWritten, TRUE))
                    fRes = FALSE;
                else
                    fRes = TRUE;
            }
        }
        else
            fRes = TRUE;

        CloseHandle(osWrite.hEvent);

        SetEvent(this->ReadEvent);
    }

    int Serial::Run() {

        param.fd = this->hCom;
        param.bind_function = this->call_function;

        param.args = this->max_queue_size;
        param.SendEvent = &this->SendEvent;
        param.StopEvent = &this->StopEvent;
        param.ReadEvent = &this->ReadEvent;
        message = new Message(param.head,2);
        message->BindPackageCheck(this->check_function);

        HANDLE hThread1 = CreateThread(NULL, 0, recive_serial_data, &param, 0, NULL);

        return 0;
    }

    bool Serial::Lock() {
        WaitForSingleObject(ReadEvent, INFINITE);
        ResetEvent(ReadEvent);
        return false;
    }
    void Serial::Release() {
        SetEvent(StopEvent);
        CloseHandle(this->hCom);
    }

}
#endif